﻿using System.Linq.Expressions;
using BaseRepository.Db.UnitOfWork;
using Common;
using Common.DataModels;
using Microsoft.EntityFrameworkCore;

namespace BaseRepository.Db;

public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : AggregateRoot
{
    protected IUnitOfWork _unitOfWork;
    private DbSet<TEntity> _db { get; }
    public IQueryable<TEntity> Qyery { get; }
    public DbContext Context { get; }

    public BaseRepository(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
        Context = _unitOfWork.GetDbClient();
        _db =Context.Set<TEntity>();
        Qyery = _db;
    }

    /// <summary>
    /// 获取单个对象
    /// </summary>
    /// <param name="whereExpression"></param>
    /// <param name="isTracking"></param>
    /// <returns></returns>
    public Task<TEntity?> GetEntityAsync(Expression<Func<TEntity, bool>> whereExpression, bool isTracking = false)
    {
        ArgumentNullException.ThrowIfNull(whereExpression);
        if (!isTracking)
        {
            return _db.AsNoTracking().FirstOrDefaultAsync(whereExpression);
        }
        return _db.FirstOrDefaultAsync(whereExpression);
    }
    /// <summary>
    /// 获取多个实体
    /// </summary>
    /// <param name="whereExpression"></param>
    /// <param name="isTracking"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<List<TEntity>> GetEntitiesAsync(Expression<Func<TEntity, bool>> whereExpression, bool isTracking = false)
    {
        ArgumentNullException.ThrowIfNull(whereExpression);
        if (!isTracking)
        {
            return _db.AsNoTracking().Where(whereExpression).ToListAsync();
        }

        return _db.Where(whereExpression).ToListAsync();
    }

    /// <summary>
    /// 根据排序获取多个对象
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="whereExpression"></param>
    /// <param name="orderStr"></param>
    /// <param name="isAsc"></param>
    /// <param name="isTracking"></param>
    /// <returns></returns>
    public Task<List<TEntity>> GetEntitiesByOrderAsync(Expression<Func<TEntity, bool>> whereExpression, string orderStr = "", bool isTracking = false)
    {
        ArgumentNullException.ThrowIfNull(whereExpression);
        var temp = _db.Where(whereExpression);
        if (!string.IsNullOrWhiteSpace(orderStr))
        {
            temp = temp.OrderByDynamic(orderStr);
        }

        if (!isTracking)
        {
            temp = temp.AsNoTracking();
        }
        return temp.ToListAsync();
    }
    /// <summary>
    /// 分页和排序获取多个对象
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="whereExpression"></param>
    /// <param name="orderStr"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <param name="isTracking"></param>
    /// <returns></returns>
    public async Task<Tuple<List<TEntity>, int>> GetEntitiesByPageAsync(Expression<Func<TEntity, bool>> whereExpression, string? orderStr = "", int pageIndex = 1, int pageSize = 20, bool isTracking = false)
    {
        ArgumentNullException.ThrowIfNull(whereExpression);
        var temp = _db.Where(whereExpression);
        if (!string.IsNullOrWhiteSpace(orderStr))
        {
            temp = temp.OrderByDynamic(orderStr);
        }
        if (!isTracking)
        {
            temp = temp.AsNoTracking();
        }

        temp = temp.Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking();
        var dataCount = await temp.CountAsync();
        var data = await temp.ToListAsync();
        return new Tuple<List<TEntity>, int>(data, dataCount);
        //return new PageModel<TEntity>(pageIndex, pageSize, dataCount, data);
    }
    /// <summary>
    /// 分页获取多个对象
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <param name="whereExpression"></param>
    /// <param name="pageIndex"></param>
    /// <param name="pageSize"></param>
    /// <param name="isTracking"></param>
    /// <returns></returns>
    public async Task<Tuple<List<TEntity>, int>> GetEntitiesByPageAsync(Expression<Func<TEntity, bool>> whereExpression, int pageIndex = 1, int pageSize = 20, bool isTracking = false)
    {
        var temp = _db.Where(whereExpression);
        var dataCount = await temp.CountAsync();
        temp = temp.Skip((pageIndex - 1) * pageSize);
        if (!isTracking)
        {
            temp = temp.AsNoTracking();
        }
        var data = await temp.ToListAsync();
        return new Tuple<List<TEntity>, int>(data, dataCount);
        //return new PageModel<TEntity>(pageIndex, pageSize, dataCount, data);
    }
    /// <summary>
    /// 添加对象
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<int> CreateAsync(TEntity entity)
    {
        _db.Add(entity);
        return _unitOfWork.SaveDbContextAsync();
    }
    /// <summary>
    /// 添加多个
    /// </summary>
    /// <param name="entities"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<int> CreateAsync(IEnumerable<TEntity> entities)
    {
        _db.AddRange(entities);
        return _unitOfWork.SaveDbContextAsync();
    }
    ///// <summary>
    ///// 高效批量插入
    ///// </summary>
    ///// <param name="entities"></param>
    ///// <returns></returns>
    //public Task BulkInsert(IEnumerable<TEntity> entities)
    //{
    //    return _unitOfWork.GetDbClient().BulkInsertAsync(entities);
    //}
    /// <summary>
    /// 更新对象
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<int> UpdateAsync(TEntity entity)
    {
        _db.Update(entity);
        return _unitOfWork.SaveDbContextAsync();
    }
    /// <summary>
    /// 更新多个对象
    /// </summary>
    /// <param name="entities"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<int> UpdateAsync(IEnumerable<TEntity> entities)
    {
        _db.UpdateRange(entities);
        return _unitOfWork.SaveDbContextAsync();
    }
    /// <summary>
    /// 删除对象
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<int> DeleteAsync(long id)
    {
        //_db.Remove(entity);
        //return _unitOfWork.SaveDbContextAsync();
        return _db.Where(p => p.Id == id).ExecuteDeleteAsync();
    }
    /// <summary>
    /// 删除多个对象
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public Task<int> DeleteAsync(IEnumerable<long> ids)
    {
        //_db.RemoveRange(entities);
        //return _unitOfWork.SaveDbContextAsync();
        ArgumentNullException.ThrowIfNull(ids);
        return _db.Where(p => ids.Contains(p.Id)).ExecuteDeleteAsync();
    }
    /// <summary>
    /// 假删  这边有service来实现
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    //public Task<int> FalseDeletionAsync(IEnumerable<long> ids)
    //{
    //    ArgumentNullException.ThrowIfNull(ids);
    //    return _db.Where(p => ids.Contains(p.Id)).ExecuteUpdateAsync(p => p.SetProperty(o => o.IsDelete, true));
    //}
}